#include <ulib.h>
#include <stdio.h>
#include <thread.h>

#define   MAX_LOOP 1000
#define   MAX_ELEM 64
#define   PRIME1   103072243
#define   PRIME2   103995407
const int NumProcs=2;
/* shared variables */
int sig[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int m[MAX_ELEM];
int error_iter=0;
int mix(int i, int j) {
	return (i+j*PRIME2)%PRIME1;
}

int racey_proc1()
{
	int i;
	int tid=1;
	cprintf("In racey process num %d\n ",tid);
	for(i=0;i<MAX_LOOP;i++) {
		cprintf("In racey process1 i = %d\n ",i);
		unsigned num=sig[tid];
		unsigned index1=num%MAX_ELEM;
		unsigned index2;
		num=mix(num,m[index1]);
		index2=num%MAX_ELEM;

		if (error_iter==3) error_iter=3/0;
	
		num=mix(num,m[index2]);
		m[index2]=num;
		sig[tid]=num;
	}
	error_iter=error_iter+1;
return 0; 
}

int racey_proc2()
{
	int i;
	int tid=2;
	cprintf("In racey process num %d\n ",tid);
	for(i=0;i<MAX_LOOP;i++) {
		cprintf("In racey process2 i = %d\n ",i);
		unsigned num=sig[tid];
		unsigned index1=num%MAX_ELEM;
		unsigned index2;
		num=mix(num,m[index1]);
		index2=num%MAX_ELEM;
		num=mix(num,m[index2]);
		m[index2]=num;
		sig[tid]=num;
	}
return 0; 
}

int main(void) {
	int mix_sig,i,j;
	thread_t tids[NumProcs];
	cprintf("in test_racey\n");	
	for (i=0;i<MAX_ELEM;i++)
		m[i]=mix(i,i);
	for (j=0;j<5;j++) {
		for (i=0;i<NumProcs;i++) {
		    if (i==0) {
		    	if (thread(racey_proc1, NULL, tids + i) != 0) {
		    		cprintf("When create %dth racey process",i+1);
		    		goto failed;
		    	}
		    }
		    else {
		    	if (thread(racey_proc2, NULL, tids + i) != 0) {
		    		cprintf("When create %dth racey process",i+1);
		    		goto failed;
		    	}
		    }
		}
		int count=0;
    		while (wait()==0) count++;
	}
    
    /* compute the result */
    mix_sig=sig[0];
    for (i=1;i<NumProcs;i++)
    	mix_sig=mix(sig[i],mix_sig);
    /* print results */
    cprintf("\n\nShort signature: %08x @ %p\n\n\n", mix_sig, &mix_sig);

return 0;
failed:
    for (i = 0; i < NumProcs; i ++)
        if (tids[i].pid > 0) kill(tids[i].pid);
    panic("FAIL: T.T\n");
}
